//
// Created by fairy on 2025/7/28.
//

#ifndef VARIABLE_HPP
#define VARIABLE_HPP
#include <algorithm>
#include <concepts>
#include <cstdint>
#include <type_traits>

namespace utils::detail_Variable {
    // 类型特征：判断是否为小对象（在寄存器中高效传递）
    template<typename T>
    struct is_small_object {
        // 根据目标架构调整阈值（ARM Cortex-M 通常≤64bit）
        static constexpr bool value = sizeof(T) <= 2 * sizeof(void *);
    };

    template<typename T>
    inline constexpr bool is_small_object_v = is_small_object<T>::value;

    // 约束概念：必须可转换为位偏移（枚举或整数）
    template <typename T>
    concept BitOffset = requires(T value) {
        { static_cast<std::size_t>(value) } -> std::convertible_to<std::size_t>;
    };
}

namespace utils {

    /**
     * 状态变量
     * @tparam T 变量类型
     * @note 对于基本类型如int、float等，如果是只读不修改，那么使用值传递更加高效，因为使用的是寄存器，几乎没有开销。而对于对象或者大型结构体来说，使用引用更加高效，因为只传入了一个指针。
     *      如果是修改，那么使用引用传递更优，虽然性能上可能没有提升，但是避免了空引用问题。
     *
     * @code
        常见用法是把它放到一个结构体里，用作状态变量，也可单独拿出来作为状态变量。
        // ----------------- 作为结构体的一部分 -------------------
        // 定义结构体类型
        struct UISate {
        private:
            using stateVariable = stateVariable<bool>; // 全部默认使用bool类型
        public:
            stateVariable buttonState;
            stateVariable imgbtnState;
            stateVariable beepState;
        };

        // 定义结构体变量
        UISate uiState{};

        // 清除按钮状态
        uiState.buttonState.off();

        // 设置按钮状态
        uiState.buttonState.on();

        // 查询按钮状态
        auto tempState = uiState.buttonState.read();

        // 状态循环（或者消费） 用于状态的分支控制
        if (uiState.buttonState.poll()) {
            // 其他任务
        }
        if (uiState.buttonState.consume()) {
            // 其他任务
        }

        // 交换值
        auto old_value = uiState.buttonState.exchange(false);

        // ----------------- 作为单独变量 -------------------
        // 使用32位来存储状态
        stateVariable<uint32_t> buttonState{};

        // 定义状态类型
        enum class ButtonState:uint32_t {
            pressed = 0,
            released = 1,
            hold = 2,
            long_pressed = 3,
            long_hold = 4,
        };

        // 设置状态
        buttonState.write(2);
        buttonState.write(ButtonState::hold);

        // 查询状态
        if (buttonState.read() == 2) {
        }
        if (buttonState.read_as<ButtonState>() == ButtonState::hold) {
        }
        if (buttonState.read_as(ButtonState::hold) == ButtonState::hold) {
        }

        // 轮询状态（或者消费状态）
        if (buttonState.poll(2)) {
        }
        if (buttonState.poll(ButtonState::hold)) {
        }
        if (buttonState.consume(2)) {
        }
        switch (buttonState.consume(ButtonState::hold)) {
            case ButtonState::hold:
                break;

            default:
                break;
        }

        // 交换状态
        const auto oldState = buttonState.exchange(ButtonState::pressed);
        ButtonState tempButtonState = oldState;
     * @endcode
     */
    template<typename T>
        requires (detail_Variable::is_small_object_v<T> || std::is_trivially_copyable_v<T>)
    class stateVariable {
        T value_;

    public:
        stateVariable() = default;

        // 使用成员初始化列表
        explicit stateVariable(T data) noexcept : value_(data) {}


        // 禁止复制以保证原子性
        stateVariable(const stateVariable &) = delete;

        stateVariable &operator=(const stateVariable &) = delete;

        // 运算符重载
        constexpr explicit operator T() const noexcept {
            return value_;
        }

        [[gnu::always_inline]] constexpr void write(T new_val) noexcept {
            value_ = new_val;
        }

        // 枚举类型的专用写操作
        template<typename Enum>
            requires std::is_enum_v<Enum> &&
                     std::is_same_v<std::underlying_type_t<Enum>, T>
        [[gnu::always_inline]] constexpr void write(Enum new_val) noexcept {
            value_ = static_cast<T>(new_val);
        }

        // // 通用数值写操作 - 接受任何数值类型
        template<typename U>
        [[gnu::always_inline]] constexpr void write(U new_val) noexcept
            requires ((std::is_integral_v<U> || std::is_enum_v<U>) &&
                      std::is_convertible_v<U, T> &&
                      !std::is_same_v<std::remove_cvref_t<U>, T>)
        {
            value_ = static_cast<T>(new_val);
        }

        [[gnu::always_inline]] [[nodiscard]] constexpr const T &read() const noexcept { return value_; }

        /**
         * 读取为指定枚举类型
         *
         * @tparam Enum 枚举类型
         * @param expected_value 预期的枚举值（用于类型推导）
         * @return Enum 转换为指定枚举类型的值
         */
        template<typename Enum>
            requires std::is_enum_v<Enum> &&
                     std::is_same_v<std::underlying_type_t<Enum>, T>
        [[gnu::always_inline]] [[nodiscard]] constexpr Enum read_as(Enum expected_value) const noexcept {
            (void) expected_value; // 仅用于类型推导，不需要实际值
            return static_cast<Enum>(value_);
        }

        /**
         * 直接读取为枚举类型（不需要参数）
         *
         * @tparam Enum 枚举类型
         * @return Enum 转换为指定枚举类型的值
         */
        template<typename Enum>
            requires std::is_enum_v<Enum> &&
                     std::is_same_v<std::underlying_type_t<Enum>, T>
        [[gnu::always_inline]] [[nodiscard]] constexpr Enum read_as() const noexcept {
            return static_cast<Enum>(value_);
        }

        // poll() 函数 - 统一使用按值传递（效率足够且避免移动问题）
        [[gnu::always_inline]] constexpr bool poll(T clear_state)
            requires std::equality_comparable<T> {
            const bool result = (value_ != clear_state);
            value_ = clear_state;
            return result;
        }

        template<typename Enum>
        [[gnu::always_inline]]
        constexpr bool poll(Enum &&clear_state) noexcept
            requires (std::equality_comparable<T> && std::is_enum_v<Enum> && std::is_same_v<std::underlying_type_t<Enum>
                          , T>) {
            const bool result = (value_ != static_cast<T>(clear_state));
            value_ = static_cast<T>(std::forward<Enum>(clear_state));
            return result;
        }

        // consume() 函数 - 优化版本
        [[gnu::always_inline]] constexpr T consume() noexcept requires std::is_nothrow_default_constructible_v<T> {
            return exchange(T{});
        }

        [[gnu::always_inline]] constexpr T consume(const T &clear_state) noexcept {
            return exchange(clear_state);
        }

        [[gnu::always_inline]] constexpr T consume(T &&clear_state) noexcept {
            return exchange(std::move(clear_state));
        }

        template<typename Enum>
        [[gnu::always_inline]] constexpr Enum consume(Enum &&clear_state) noexcept
            requires std::is_enum_v<Enum> && std::is_same_v<std::underlying_type_t<Enum>, T> {
            Enum old = static_cast<Enum>(value_);
            value_ = static_cast<T>(std::forward<Enum>(clear_state));
            return old;
        }


        // exchange() 统一实现
        // 基础版本
        [[gnu::always_inline]] constexpr T exchange(T new_val) noexcept {
            T old = value_;
            value_ = new_val;
            return old;
        }

        // 枚举特化版本
        template<typename Enum>
            requires std::is_enum_v<Enum> &&
                     std::is_same_v<std::underlying_type_t<Enum>, T>
        [[gnu::always_inline]] constexpr Enum exchange(Enum new_val) noexcept {
            Enum old = static_cast<Enum>(value_);
            value_ = static_cast<T>(new_val);
            return old;
        }


        // ---------- bool类型特化函数 ----------
        [[gnu::always_inline]] constexpr void toggle() requires std::same_as<T, bool> {
            value_ = !value_;
        }

        [[gnu::always_inline]] constexpr void on() requires std::same_as<T, bool> {
            value_ = true;
        }

        [[gnu::always_inline]] constexpr void off() requires std::same_as<T, bool> {
            value_ = false;
        }

        [[gnu::always_inline]] constexpr bool poll() requires std::same_as<T, bool> {
            const bool result = value_;
            value_ = false;
            return result;
        }


    };

    /**
     * 位状态变量
     * @details 每一位都是一个状态，即每个状态都是相互独立的
     * @tparam T 存储类型，为无符号整型
     * @code
        // 单独使用
        bitStateVariable<uint8_t> bitState{};
        bitState.set_bit(2);
        bitState.clear_bit(2);
        bitState.toggle_bit(2);
        auto tempBit = bitState.get_bit(2);

        // 更规范的使用
        enum class BitState:uint8_t {
            buttonState = 0,
            imgbtnSate = 1,
            beepState = 2,
        };
        bitState.set_bit(BitState::beepState);
        bitState.clear_bit(BitState::beepState);
        bitState.toggle_bit(BitState::beepState);

        if (bitState.get_bit(BitState::beepState)) {
        }
        @endcode
     */
    template<typename T>
    requires std::unsigned_integral<T>
    class bitStateVariable {
        T value_;
    public:
        bitStateVariable() = default;
        explicit bitStateVariable(T data) : value_(data){}

        // ---------- 无符号整型特化函数 ----------
        // 设置特定位
        [[gnu::always_inline]] constexpr void set_bit(std::size_t bit) noexcept  {
            value_ |= static_cast<T>(1) << bit;
        }

        template<typename Enum>
        [[gnu::always_inline]] constexpr void set_bit(Enum bit) noexcept
            requires (std::is_enum_v<Enum>) {
            value_ |= static_cast<T>(1) << static_cast<T>(bit);
        }

        // 清除特定位
        [[gnu::always_inline]] constexpr void clear_bit(std::size_t bit) noexcept {
            value_ &= ~(static_cast<T>(1) << bit);
        }

        template<typename Enum>
        [[gnu::always_inline]] constexpr void clear_bit(Enum bit) noexcept
            requires (std::is_enum_v<Enum>) {
            value_ &= ~(static_cast<T>(1) << static_cast<T>(bit));
        }

        // 翻转特定位
        [[gnu::always_inline]] constexpr void toggle_bit(std::size_t bit) noexcept {
            value_ ^= static_cast<T>(1) << bit;
        }

        template<typename Enum>
        [[gnu::always_inline]] constexpr void toggle_bit(Enum bit) noexcept
            requires (std::is_enum_v<Enum>) {
            value_ ^= static_cast<T>(1) << static_cast<T>(bit);
        }


        // 检查特定位状态
        [[gnu::always_inline]] [[nodiscard]] constexpr bool get_bit(std::size_t bit) const noexcept {
            return (value_ >> bit) & static_cast<T>(1);
        }

        template<typename Enum>
        [[gnu::always_inline]] [[nodiscard]] constexpr bool get_bit(Enum bit) const noexcept
            requires (std::is_enum_v<Enum>) {
            return (value_ >> static_cast<T>(bit)) & static_cast<T>(1);
        }

        // 设置多个位（掩码操作）
        [[gnu::always_inline]] constexpr void set_bits(T mask) noexcept {
            value_ |= mask;
        }

        template<typename Enum>
        [[gnu::always_inline]] constexpr void set_bits(Enum mask) noexcept
            requires (std::is_enum_v<Enum>) {
            value_ |= static_cast<T>(mask);
        }

        // 清除多个位（掩码操作）
        [[gnu::always_inline]] constexpr void clear_bits(T mask) noexcept {
            value_ &= ~mask;
        }

        template<typename Enum>
        [[gnu::always_inline]] constexpr void clear_bits(Enum mask) noexcept
            requires (std::is_enum_v<Enum>) {
            value_ &= ~static_cast<T>(mask);
        }

        /**
         * 获取多个位状态
         * @tparam Offsets 可以转为位偏移的类型
         * @param offsets 位状态参数包
         * @return 对应位状态bool值的元组
         * @code
        *   enum class BitState : uint8_t { button = 0, imgbtn = 1, beep = 2 };
            bitStateVariable<uint8_t> state;

            // 设置位
            state.set_bit(BitState::button);
            state.clear_bit(BitState::beep);

            // 获取所有位的状态（结构化绑定）
            auto [bit_buttonState,bit_imgbtnState,bit_beepState] = bitState.get_bits(BitState::button, BitState::imgbtn, BitState::beep);
            auto one = bitState.get_bits(BitState::buttonState, BitState::imgbtn, BitState::beep);

            // 多个状态同时满足
            if (bitState.get_bits_and(BitState::button, BitState::imgbtn, BitState::beep)) {
            }

            // 多个状态至少有一个满足
            if (bitState.get_bits_or(BitState::button, BitState::imgbtn, BitState::beep)) {
            }
         * @endcode
         */
        template <detail_Variable::BitOffset... Offsets>
        [[gnu::always_inline]] [[nodiscard]] constexpr auto get_bits(Offsets... offsets) const noexcept
            -> std::tuple<decltype(get_bit(offsets))...>
        {
            return { get_bit(static_cast<std::size_t>(offsets))... };
        }


        // 返回多个状态同时满足的结果
        template <detail_Variable::BitOffset... Offsets>
        [[gnu::always_inline]] [[nodiscard]] constexpr bool get_bits_and(Offsets... offsets) const noexcept {
            return (get_bit(static_cast<std::size_t>(offsets)) && ...);
        }

        // 返回多个状态至少有一个满足的结果
        template <detail_Variable::BitOffset... Offsets>
        [[gnu::always_inline]] [[nodiscard]] constexpr bool get_bits_or(Offsets... offsets) const noexcept {
            return (get_bit(static_cast<std::size_t>(offsets)) || ...);
        }


        // 事件循环
        [[gnu::always_inline]] [[nodiscard]] constexpr bool poll(T bit) noexcept {
            return (value_ & (static_cast<T>(1) << bit)) != 0;
        }

        template<typename Enum>
        [[gnu::always_inline]] [[nodiscard]] constexpr bool poll(Enum bit) noexcept
            requires (std::is_enum_v<Enum>) {
            return ((value_ & (static_cast<T>(1) )<< static_cast<T>(bit))) != 0;
        }
    };
}


#endif //VARIABLE_HPP
